fix(rename): skip stateless objects in PathsGenerator to prevent panic [PSGO-233]#2591
Open
fix(rename): skip stateless objects in PathsGenerator to prevent panic [PSGO-233]#2591
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Prevents kbc pull / rename-plan generation from panicking when the local state contains manifest-only (“stateless”) object entries (no local files and no remote API object), which can happen with orphaned scheduler configs.
Changes:
- Add guards in
PathsGenerator.doUpdateto skip stateless objects (and stateless parents) to avoidLocalOrRemoteState()panics. - Add a rename plan unit test intended to ensure stateless entries don’t break
NewPlan. - Add an e2e CLI fixture that reproduces
pull --forcewith an orphaned scheduler record plus a rename scenario.
Reviewed changes
Copilot reviewed 14 out of 22 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/pkg/state/local/paths.go | Skip stateless objects/parents during path generation to prevent LocalOrRemoteState() panic. |
| internal/pkg/plan/rename/plan_test.go | Adds a unit test around stateless entries during rename plan creation. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/args | New CLI e2e test arguments for pull --force. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/expected-code | Expected exit code for the new CLI fixture. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/expected-stderr | Expected warning output for manifest load warnings. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/expected-stdout | Expected plan + rename output for the new CLI fixture. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/initial-state.json | Initial remote state fixture for the new CLI test. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/in/.keboola/manifest.json | Input manifest containing an orphaned scheduler config and a wrongly named config. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/in/description.md | Input repository description fixture. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/in/main/description.md | Input main-branch description fixture. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/in/main/extractor/ex-generic-v2/wrong-name/config.json | Input config content fixture (pre-rename). |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/in/main/extractor/ex-generic-v2/wrong-name/description.md | Input config description fixture (pre-rename). |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/in/main/extractor/ex-generic-v2/wrong-name/meta.json | Input config metadata fixture (pre-rename). |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/in/main/meta.json | Input branch metadata fixture. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/.keboola/manifest.json | Expected cleaned manifest after pull (orphan removed, renamed paths). |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/.keboola/project.json | Expected project metadata after pull. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/description.md | Expected repository description output fixture. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/main/description.md | Expected main-branch description output fixture. |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/main/extractor/ex-generic-v2/empty/config.json | Expected config content output fixture (post-rename). |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/main/extractor/ex-generic-v2/empty/description.md | Expected config description output fixture (post-rename). |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/main/extractor/ex-generic-v2/empty/meta.json | Expected config metadata output fixture (post-rename). |
| test/cli/pull/pull-force-orphaned-scheduler-with-rename/out/main/meta.json | Expected branch metadata output fixture. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
hosekpeter
reviewed
Apr 29, 2026
Contributor
hosekpeter
left a comment
There was a problem hiding this comment.
Nit (out of scope):TestRenameAllPlan lines 51-59 action.Manifest = nil is set twice here. Could be cleaned up while we're here.
When a manifest entry exists for a config that has neither local nor remote state (e.g. an orphaned scheduler config after its target orchestrator was deleted), PathsGenerator.doUpdate called LocalOrRemoteState() which panicked unconditionally. Two guards added to doUpdate: 1. Skip the object itself when both HasLocalState and HasRemoteState are false. 2. Skip the object when its parent is stateless, since a valid path cannot be resolved without a resolved parent. Reproduces the crash in PSGO-233 / SUPPORT-15941 where kbc pull panicked on "object Local or Remote state must be set" for clients with an existing local manifest containing an orphaned scheduler entry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Regression test for PSGO-233: verifies that kbc pull --force succeeds when the manifest contains an orphaned scheduler (fake ID, no local files, not in remote) AND a config exists at a wrong path that needs to be renamed. Previously PathsGenerator.doUpdate could panic on stateless objects encountered during the rename plan. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5bcbce0 to
4329212
Compare
romanbracinik
requested changes
Apr 30, 2026
romanbracinik
left a comment
There was a problem hiding this comment.
ok fixol by som len ten test este
Remove "Ignoring invalid local state." — the orphaned scheduler "456" is removed by SetRecords at manifest-load time (stderr warning only), so no localErr is produced and the stdout message is not printed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4329212 to
c6695db
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PathsGenerator.doUpdatecallsobjectState.LocalOrRemoteState()unconditionally, which panics when a manifest entry exists for a config that has neither local nor remote state. This happens when an orphaned scheduler config remains in the manifest after its target orchestrator was deleted — the state entry is created from the manifest but never populated with actual data from either local files or the remote API.internal/pkg/model/objectstate.go:265→LocalOrRemoteState()→ called frominternal/pkg/state/local/paths.go:79→PathsGenerator.doUpdate→internal/pkg/plan/rename/rename.go→rename.NewPlan→sync/pullChanges
paths.go: Added two guards todoUpdate:LocalOrRemoteState()panic).plan_test.go: New testTestRenameAllPlan_StatelessObjectSkippedinjects a statelessConfigStateinto a loaded state and assertsNewPlanreturns without error and excludes the orphan from rename actions.Relation to previous fixes
PR #2580 fixed the naming registry collision. PR #2585 fixed the manifest
SetRecordsfail-fast and orphaned-scheduler handling inpush/diff. This PR fixes the remaining crash path that triggers duringkbc pullwhen the rename plan builder encounters the stateless state entry that those earlier fixes may not have fully cleaned up.Test plan
go test -race ./internal/pkg/plan/rename/... -run TestRenameAllPlango test -race ./internal/pkg/state/local/...kbc pullon a project with an orphaned scheduler config in the local manifest — should complete without crashingFixes PSGO-233 / SUPPORT-15941 (follow-up crash after #2585)
🤖 Generated with Claude Code